package com.sxt.config;


import java.util.HashMap;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.IRedisManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class ShiroConfig {

	@Value("${spring.redis.host:127.0.0.1}")
	private String redisHost;

	@Value("${spring.redis.port:6379}")
	private Integer redisPort ;

	@Value("${spring.redis.jedis.pool.max-active:10}")
	private Integer maxTotal;

	@Value("${spring.redis.jedis.pool.max-idle:8}")
	private Integer maxIdle;

	@Value("${spring.redis.jedis.pool.min-idle:5}")
	private Integer minIdle;
	/**
	 * 创建SecurityManager
	 * 
	 */
	@Bean
	public DefaultWebSecurityManager defaultWebSecurityManager(DefaultWebSessionManager defaultWebSessionManager, SessionDAO redisSession,UserRealm userRealm,CredentialsMatcher credentialsMatcher) {
		DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
		// 设置userRealm
		userRealm.setCredentialsMatcher(credentialsMatcher);
		defaultWebSecurityManager.setRealm(userRealm);
		defaultWebSessionManager.setSessionDAO(redisSession);
		defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);
		return defaultWebSecurityManager ;
	}

	/**
	 * sessionManager 里面可以决定sessionDAO
	 * @param redisSessionDao
	 * @return
	 */
	//	@Bean
	//	public DefaultWebSessionManager defaultWebSessionManager(SessionDAO redisSessionDao) {
	//		DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
	//		defaultWebSessionManager.setSessionDAO(redisSessionDao);
	//		return defaultWebSessionManager ;
	//	}
	/**
	 * 使用Redis  来存储登录的信息
	 *sessionDao 还需要设置给sessionManager
	 */
	@Bean
	public SessionDAO redisSessionDAO(IRedisManager redisManager) {
		RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
		redisSessionDAO.setRedisManager(redisManager); //操作那个redis
		redisSessionDAO.setExpire(7*24*3600); // 用户的登录信息保存多久？ 7 天
		//       redisSessionDAO.setKeySerializer(keySerializer); jdk
		//       redisSessionDAO.setValueSerializer(valueSerializer);jdk
		return redisSessionDAO ;
	}

	@Bean
	public IRedisManager  redisManager() {
		RedisManager redisManager = new RedisManager();
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxTotal(maxTotal); // 链接池的最量 20 ，并发特别大时，连接池的数据可以最大增加20个
		jedisPoolConfig.setMaxIdle(maxIdle);// 连接池的最大剩余量15个 ：并发不大，池里面的对象用不上，里面对象太多了。浪费空间
		jedisPoolConfig.setMinIdle(minIdle); // 连接池初始就有10 个
		JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort);
		redisManager.setJedisPool(jedisPool );
		return redisManager ;
	}

	/**
	 * 密码匹配器
	 * @return
	 */
	@Bean
	public CredentialsMatcher credentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher("MD5");
		hashedCredentialsMatcher.setHashIterations(2);
		return hashedCredentialsMatcher;
	}
	/**
	 * 过滤器放行链
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setLoginUrl("/login"); // 这次跳转是get 请求
		shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");// 这次跳转是get 请求
		HashMap<String, String> filterChainDefinitionMap = new HashMap<String, String>();
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/unauthorized", "anon");
		filterChainDefinitionMap.put("/captcha.jpg", "anon");
//		filterChainDefinitionMap.put("/**", "authc");
		filterChainDefinitionMap.put("/**", "anon"); // 测试环境使用它，将非常方便的和swagger 集成
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		return shiroFilterFactoryBean ;
	}

	/**
	 * 基于注解的权限验证方式
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
		return authorizationAttributeSourceAdvisor;
	}
	/**
	 * 代理对象的创建
	 * 
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		// TURE FALSE
		// FALSE : 采用的是jdk的形式：若该类由接口，则使用jdk ，没有接口使用cglib
		//		defaultAdvisorAutoProxyCreator.setProxyTargetClass(false);
		return defaultAdvisorAutoProxyCreator ;
	}
}
